package com.y.fund.utils;

import java.nio.charset.StandardCharsets;
import java.security.SecureRandom;
import java.util.Arrays;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

public class AESUtil {
	
    /** AES algorithm size 128 */
	public static final int AES128 = 128;

	/**
	 * 生成AES的key并使用Hex位编码
	 */
	public static String generateHexKey(String k){
		try {
			return StrUtil.bytes2HexStr(generateKey(k).getEncoded());
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	private static SecretKey generateKey(String k) throws Exception{
		KeyGenerator kgen = KeyGenerator.getInstance("AES");
		SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");  
		secureRandom.setSeed(k.getBytes("UTF-8"));
		kgen.init(AES128, secureRandom);
		return kgen.generateKey();
	}
	
	
    /**  
   	* @param str String to be encrypted
	* @param hexKeyEncoded  Required item: secretkey Encoded hexadecimal encoding
	* @return Encrypted byte array
	* @throws Exception  
	*/
	public static String encryptByHexkey(String str, String hexKeyEncoded){
		if(null==str || null==hexKeyEncoded){
			return null;
		}
		try {
			IvParameterSpec ivSpec = new IvParameterSpec(bytesFill16Length(hexKeyEncoded.getBytes(StandardCharsets.UTF_8)));
			SecretKeySpec key = new SecretKeySpec(StrUtil.hex2Bytes(hexKeyEncoded), "AES");
			Cipher enc = Cipher.getInstance("AES/CBC/PKCS5Padding");
			enc.init(Cipher.ENCRYPT_MODE, key, ivSpec);
			byte[] t = enc.doFinal(str.getBytes(StandardCharsets.UTF_8));
		    return StrUtil.bytes2HexStr(t);
		} catch (Exception e) {
			e.printStackTrace();
		}
	    return null;
	}
	
	  /** 
	   * @param str Byte array to be decrypted
	   * @param hexKeyEncoded Required item: secretkey Encoded hexadecimal encoding
	   * @return Decrypted byte array
	   * @throws Exception  
	   */
	public static String decryptByHexkey(String str, String hexKeyEncoded){
		if(null == str || null==hexKeyEncoded){
			return null;
		}
		try{
			IvParameterSpec ivSpec = new IvParameterSpec(bytesFill16Length(hexKeyEncoded.getBytes(StandardCharsets.UTF_8)));
			SecretKeySpec key = new SecretKeySpec(StrUtil.hex2Bytes(hexKeyEncoded), "AES");
			Cipher enc = Cipher.getInstance("AES/CBC/PKCS5Padding");
			enc.init(Cipher.DECRYPT_MODE, key, ivSpec);
			byte[] t = enc.doFinal(StrUtil.hex2Bytes(str));
			return new String(t, StandardCharsets.UTF_8);
		}catch(Exception e){
			e.printStackTrace();
		}
		return null;
	}

	/** The original byte array is processed to a length of just 16 bits and returned */
	public static byte[] bytesFill16Length(byte [] ob){
		if(null == ob){
			return new byte[]{'0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'};
		}
		if(ob.length < 16){
			byte [] tb = new byte[]{'0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'};
			System.arraycopy(ob, 0, tb, 0, ob.length);
			return tb;
		}else if(ob.length > 16){
			return Arrays.copyOf(ob, 16);
		}else{
			return ob;
		}
	}
	
	
	public static void main(String [] args) {
		/*
		 username=员工工号
		 password=hbd:17455654456456:C8A979B6E792FC9D4758077A7FEB8DE7

			password 组成部分： 
			hbd:  前缀，用于与普通登录密码区分
			17455654456456：随机数或时间戳，用于增加加密的随机性
			C8A979B6E792FC9D4758077A7FEB8DE7： （随机数 + 员工工号）后的AES128加密串，解密后，去掉前面的随机数就是员工工号，如果与username一致，表示一切正常，成功登录。
		 */
		
		final String aesKey = generateHexKey("D_X_AK01");
		
		/*交付平台造密钥 */
		String username = "sysadmin";
		String nonceStr = "" + System.currentTimeMillis();
		String astr = encryptByHexkey(nonceStr + username, aesKey);
		System.out.println("加密随机字符串为：" + nonceStr);
		System.out.println("加密后的密码为：" + astr);
		
		/* 交付平台 使用登录信息 请求 XR 登录接口， */
		String loginName = username;
		String password = "hbd:"+nonceStr + ":"+astr;
		
		
		/* XR平台的登录方法中解析请求参数  */
		String reqUserName = username; //从请求体中获取
		String reqPwd = password; //从请求体中获取加密串

		System.out.println("================================================");
		System.out.println("交付平台请求的账号名为：" + reqUserName);
		System.out.println("交付平台请求的密码为：" + reqPwd);

		System.out.println("================================================");
		if(reqPwd!=null && reqPwd.startsWith("hbd:")) {
			/*说明是交付平台提交的登录*/
			String [] pstr = reqPwd.split(":");
			if(pstr.length!=3) {
				return ; // "登录密码格式错误"
			}
			String nstr = pstr[1];
			String aesp = pstr[2];//实际的加密串
			String originalStr = decryptByHexkey(aesp, aesKey);
			System.out.println("解密后的原始内容串为：" + originalStr);
			if(null==originalStr || !originalStr.equals(nstr+reqUserName)) {
				return ;//密码不匹配
			}
			System.out.println("登录成功， 登录员工号为："+ reqUserName);
			//密码匹配成功
			//使用reqUserName即员工编号进行登录token的构造
			
			return ;//返回正确的登录token
		}
		
	}
	
	
	
	
	
	
	
	
	
	
	
}